package com.bosch.in.jfree.chart;


import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.LegendItemCollection;
import org.jfree.chart.LegendItemSource;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.DatasetRenderingOrder;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.chart.renderer.category.StackedBarRenderer;
import org.jfree.chart.title.LegendTitle;
import org.jfree.chart.urls.CategoryURLGenerator;
import org.jfree.data.category.CategoryDataset;
import org.jfree.ui.HorizontalAlignment;
import org.jfree.ui.RectangleEdge;
import org.jfree.ui.VerticalAlignment;
/**
 * <p>
 * <b>Title: </b> AbstractDualAxisStackedBarLineChart
 * </p>
 * <p>
 * <b>Description: </b>This class contains the general methods for the
 * generation of dual axis bar line chart on CategoryPlot. Any of the method of this
 * class could be overridden, if required. <br>
 * <ul>
 * <li>
 * Primary Chart (On left Y-Axis) - Bar Chart
 * <li>
 * Secondary Chart (On right Y-Axis) - Line Chart (optional)
 * <li>
 * Ternary Chart (On left Y-Axis) - Line Chart (optional)
 * </ul>
 * </P>
 * <p>
 * <b>Copyright: (c) </b>2011
 * </p>
 * <p>
 * <b>Company: </b> Robert Bosch India Limited
 * </p>
 * 
 * @author �m�t ��m� [apn1kor]
 * @version 1.0 June 15, 2011
 */
public abstract class AbstractDualAxisDoubleBarLineChart extends AbstractChart {

	private static final Logger LOG = Logger
			.getLogger(AbstractDualAxisDoubleBarLineChart.class);

	private static final BasicStroke dashedStroke = new BasicStroke(
            2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
            1.0f, new float[] {6.0f, 6.0f}, 0.0f);

	private int baseDashIndex;
	private String title;
	private String labelColor;
	private String titleColor;
	private int maxRange;
	private String yAxisLabel;
	
	/**
	 * Default constructor
	 * @param title
	 */
	public AbstractDualAxisDoubleBarLineChart(String... title)
	{
		initialize();
		if (title.length>0)
			{
				this.title = title[0];
			}
	}
	
	/**
	 * Initialization
	 */
	private void initialize()
	{
		labelColor	= "#0000FF";
		titleColor	= "#0000FF";
		maxRange = 0;
		yAxisLabel = null;
		baseDashIndex = 3;
		title = "";
	}
	
	/**
	 * CreateChart image and output to temporary file
	 */
	public final String createChart(HttpServletRequest request,
			PrintWriter printWriter, int width, int height, String saveTofilepath) throws IOException {
		LOG.debug("<AbstractDualAxisBarLineChart.createChart()");

		// --Create chart
		JFreeChart chart = null;

		// Domain axis label
		String xAxisTitle = getLabelXAxis();

		// range axis label
		String leftYAxisTitle = getLabelYAxisLeft();

		// get dataset
		CategoryDataset dataset1 = createDatasetLeftAxis();

		// create chart
		chart = ChartFactory.createStackedBarChart(title, // chart title
				xAxisTitle, // domain axis label
				leftYAxisTitle,// range axis label
				dataset1, // data
				PlotOrientation.VERTICAL, // orientation
				true, // include legend
				true, // tooltips?
				true // URLs?
				);
		// change the title text
		chart.getTitle().setFont(new Font(FONT_FAMILY, Font.BOLD, 16));
		chart.getTitle().setPaint(Color.decode(this.titleColor));
		chart.getTitle().setPadding(0.5, 0.2, 0.2, 0.2);

		final CategoryPlot plot = getCustomizedPlot(chart);

		// ***** Left Y-axis Properties ***** //
		final StackedBarRenderer renderer = (StackedBarRenderer) plot
				.getRenderer();
		renderer.setDrawBarOutline(true);
		renderer.setBaseItemLabelsVisible(true);
		renderer.setShadowPaint(Color.decode("#FFFFFF"));

		CategoryURLGenerator urlGeneratorLeftYAxis = getURLGeneratorLeftYAxis();
		if (null != urlGeneratorLeftYAxis) {
			renderer.setBaseItemURLGenerator(urlGeneratorLeftYAxis);
		}
		renderer.setBaseToolTipGenerator(getToolTipGeneratorLeftYAxis());
		Color[] leftAxisColors = getLeftAxisColors();
		if (leftAxisColors != null) {
			for (int i = 0; i < leftAxisColors.length; i++) {
				renderer.setSeriesPaint(i, leftAxisColors[i]);
			}
		}

		//turn off plot outline - LIV1HC
		//plot.setOutlineVisible(false);
		
		//set plot renderer
		plot.setRenderer(renderer);
		

		CategoryAxis domainAxis = plot.getDomainAxis();
		domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_90);
		domainAxis.setLabelFont(new Font(FONT_FAMILY, Font.ITALIC, fontSize));
		domainAxis.setLabelPaint(Color.decode(this.labelColor));

		NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
		rangeAxis.setLabelFont(new Font(FONT_FAMILY, Font.BOLD, fontSize));
		rangeAxis.setLabelPaint(Color.decode(this.labelColor));
		rangeAxis.setNumberFormatOverride(getNumberFormatLeftYAxis());
		if (maxRange>0)
		{
			rangeAxis.setUpperBound(maxRange);
		}
		if (yAxisLabel != null)
		{
			rangeAxis.setLabel(yAxisLabel);
		}
		// ***** Right Y-axis Properties ***** //
		CategoryDataset dataset2 = createDatasetRightAxis();
		if (null != dataset2) {
			setDatasetRight(plot, dataset2);
		}

		// ***** Left Y-axis Line Properties ***** //
		CategoryDataset datasetLeftLine = createDatasetLeftAxis1();

		if (null != datasetLeftLine) {
			final LineAndShapeRenderer renderer3 = new LineAndShapeRenderer();
			CategoryURLGenerator urlGeneratorLeftYAxis1 = getURLGeneratorLeftYAxis1();
			if (null != urlGeneratorLeftYAxis1) {
				renderer3.setBaseItemURLGenerator(urlGeneratorLeftYAxis1);
			}
			renderer3.setBaseToolTipGenerator(getToolTipGeneratorLeftYAxis1());
//			Shape[] shape1 = getLeftAxisShapes1();
//			if (shape1 != null) {
//				for (int i = 0; i < shape1.length; i++) {
//					renderer3.setSeriesShape(i, shape1[i]);
//				}
//			}

			Color[] leftAxisColors1 = getLeftAxisColors1();
			if (leftAxisColors1 != null) {
				for (int i = 0; i < leftAxisColors1.length; i++) {
					renderer3.setSeriesPaint(i, leftAxisColors1[i]);
					// change the line to dash line
					if (i>=baseDashIndex)
						renderer3.setSeriesStroke(i, dashedStroke);
				}
			}
			plot.setDataset(2, datasetLeftLine);
			plot.setRenderer(2, renderer3);
			plot.mapDatasetToRangeAxis(2, 0);
		}
		plot.setNoDataMessage("No Data Exist");
		// change the rendering order so the primary dataset appears "behind"
		// the other datasets...
		chart.getLegend().setVisible(false);
		chart.addLegend(setLegends(plot,getRemovableLegends()));
		// change background paint of chart(i.e. outer area)
		//chart.setBackgroundPaint(Color.decode("#E2E8EE"));
		chart.setBackgroundPaint(Color.decode("#FFFFFF"));
		//set outline for whole chart
		chart.setBorderVisible(true);
		
		plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);
		
		//set the filepath to save the image
		setFilename(saveTofilepath);
		String filename = setImage(request, printWriter, width, height, chart);
		
		//printWriter.flush();
		LOG.debug("AbstractDualAxisBarLineChart.createChart()>");
		return filename;

	}

	/**
	 * 
	 * @param plot
	 * @param dataset2
	 */
	private void setDatasetRight(final CategoryPlot plot,
			CategoryDataset dataset2) {
		// get right Y axis label
		String rightYAxislabel = getRightYAxisLabel();
		NumberAxis rangeAxis2 = new NumberAxis(rightYAxislabel);
		rangeAxis2.setLabelFont(new Font(FONT_FAMILY, Font.BOLD, fontSize));
		rangeAxis2.setLabelPaint(Color.BLUE);
		rangeAxis2.setNumberFormatOverride(getNumberFormatRightYAxis());
		plot.setRangeAxis(1, rangeAxis2);
		plot.setDataset(1, dataset2);
		plot.mapDatasetToRangeAxis(1, 1);
		final StackedBarRenderer renderer2 = new StackedBarRenderer();
		CategoryURLGenerator urlGeneratorRightYAxis = getURLGeneratorRightYAxis();
		if (null != urlGeneratorRightYAxis) {
			renderer2.setBaseItemURLGenerator(urlGeneratorRightYAxis);
		}
		renderer2.setBaseToolTipGenerator(getToolTipGeneratorRightYAxis());
		// renderer2.setSeriesPaint(0, Color.decode("#C24641"));
		Color[] rightAxisColors = getRightAxisColors();
		if (rightAxisColors != null) {
			for (int i = 0; i < rightAxisColors.length; i++) {
				renderer2.setSeriesPaint(i, rightAxisColors[i]);
			}
		}
		renderer2.setShadowPaint(Color.decode("#FFFFFF"));
		renderer2.setShadowXOffset(0.0);
		renderer2.setShadowYOffset(0.0);
		plot.setRenderer(1, renderer2);
	}
	
	/**
	 * 
	 * @param plot
	 * @param legendList
	 * @return
	 */
	private LegendTitle setLegends(CategoryPlot plot,List<String> legendList){
		LegendItemCollection legendItemsOld = plot.getLegendItems();
		final LegendItemCollection legendItemsNew = new LegendItemCollection();

		for(int i = 0; i< legendItemsOld.getItemCount(); i++){
			if(legendList!=null && legendList.size()>0){
				for (Iterator<String> iterator = legendList.iterator(); iterator.hasNext();) {
					String string = (String) iterator.next();
					if(!string.equalsIgnoreCase(legendItemsOld.get(i).getLabel())){
						legendItemsNew.add(legendItemsOld.get(i));
					}
				}
			}else{
				legendItemsNew.add(legendItemsOld.get(i));
			}
		    
		}
		LegendItemSource source = new LegendItemSource() {
		LegendItemCollection lic = new LegendItemCollection();
		{lic.addAll(legendItemsNew);}
		public LegendItemCollection getLegendItems() {  
		    return lic;
		}
		};
		LegendTitle legend = new LegendTitle(source);
		legend.setHorizontalAlignment(HorizontalAlignment.CENTER);
        legend.setVerticalAlignment(VerticalAlignment.CENTER);
        legend.setPosition(RectangleEdge.RIGHT);
        //legend.setBorder(1.0, 1.0, 1.0, 1.0);
        legend.setBorder(0.0, 0.0, 0.0, 0.0);
        legend.setVisible(true);
        legend.setMargin(1.5, 1.5, 1.5, 1.5);

		return legend;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getLabelColor() {
		return labelColor;
	}

	public void setLabelColor(String labelColor) {
		this.labelColor = labelColor;
	}

	public String getTitleColor() {
		return titleColor;
	}

	public void setTitleColor(String titleColor) {
		this.titleColor = titleColor;
	}

	public int getMaxRange() {
		return maxRange;
	}

	public void setMaxRange(int maxRange) {
		this.maxRange = maxRange;
	}

	public String getyAxisLabel() {
		return yAxisLabel;
	}

	public void setyAxisLabel(String yAxisLabel) {
		this.yAxisLabel = yAxisLabel;
	}

	public int getBaseDashIndex() {
		return baseDashIndex;
	}

	public void setBaseDashIndex(int baseDashIndex) {
		this.baseDashIndex = baseDashIndex;
	}
	
	
}
